package com.one.group.admin.excel;

import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ListUtils;
import com.one.group.admin.mapper.OwnerMapper;
import com.one.group.admin.mapper.SpHouseMapper;
import com.one.group.enums.ErrorCode;
import com.one.group.exception.BusinessException;
import com.one.group.model.entity.Owner;
import com.one.group.model.entity.SpHouse;
import com.one.group.service.OwnerService;
import com.one.group.service.SpHouseService;
import lombok.extern.slf4j.Slf4j;

import java.util.regex.Pattern;

import java.util.*;

/**
 * 业主数据读取监听器
 */
@Slf4j
public class OwnerDataReadListener implements ReadListener<OwnerData> {

    /**
     * 每隔100条存储数据库，实际使用中可以100条，然后清理list ，方便内存回收
     */
    private static final int BATCH_COUNT = 100;

    /**
     * 缓存的数据
     */
    private List<OwnerData> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

    private OwnerService ownerService;
    private OwnerMapper ownerMapper;
    private SpHouseService spHouseService;
    private SpHouseMapper spHouseMapper;
    private Long tenantId;

    // 小区名称到ID的映射缓存
    private Map<String, Long> cellNameToIdMap = new HashMap<>();

    // 性别映射
    private static final Map<String, Integer> GENDER_MAP = new HashMap<>();
    static {
        GENDER_MAP.put("男", 1);
        GENDER_MAP.put("女", 0);
        GENDER_MAP.put("1", 1);
        GENDER_MAP.put("0", 0);
    }

    // 住户身份映射
    private static final Map<String, Integer> RESIDENT_TYPE_MAP = new HashMap<>();
    static {
        RESIDENT_TYPE_MAP.put("业主", 1);
        RESIDENT_TYPE_MAP.put("子女", 2);
        RESIDENT_TYPE_MAP.put("亲戚", 3);
        RESIDENT_TYPE_MAP.put("其他", 4);
        RESIDENT_TYPE_MAP.put("1", 1);
        RESIDENT_TYPE_MAP.put("2", 2);
        RESIDENT_TYPE_MAP.put("3", 3);
        RESIDENT_TYPE_MAP.put("4", 4);
    }

    // 邮箱格式验证正则表达式
    private static final Pattern EMAIL_PATTERN = Pattern.compile(
        "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
    );

    public OwnerDataReadListener() {
    }

    /**
     * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
     * @param ownerService 业主服务
     * @param ownerMapper 业主Mapper
     * @param spHouseService 房屋服务
     * @param tenantId 租户ID
     */
    public OwnerDataReadListener(OwnerService ownerService, OwnerMapper ownerMapper, SpHouseService spHouseService,SpHouseMapper spHouseMapper, Long tenantId) {
        this.ownerService = ownerService;
        this.ownerMapper = ownerMapper;
        this.spHouseService = spHouseService;
        this.spHouseMapper = spHouseMapper;
        this.tenantId = tenantId;
        
        // 初始化时加载所有小区映射
        initCellNameMapping();
    }

    /**
     * 初始化小区名称到ID的映射
     */
    private void initCellNameMapping() {
        try {
            List<Map<String, Object>> cellList = ownerMapper.getAllCellsByTenantId(tenantId);
            for (Map<String, Object> cell : cellList) {
                String cellName = (String) cell.get("name");
                Long cellId = ((Number) cell.get("id")).longValue();
                cellNameToIdMap.put(cellName, cellId);
            }
        } catch (Exception e) {
//            log.error("加载小区映射失败", e);
            throw new RuntimeException("加载小区映射失败: " + e.getMessage());
        }
    }

    /**
     * 验证邮箱格式是否正确
     * @param email 邮箱地址
     * @return 是否有效
     */
    private boolean isValidEmail(String email) {
        if (StrUtil.isBlank(email)) {
            return true; // 空邮箱认为是有效的（可选字段）
        }
        return EMAIL_PATTERN.matcher(email.trim()).matches();
    }

    /**
     * 这个每一条数据解析都会来调用
     * @param data 一行数据
     * @param context 分析上下文
     */
    @Override
    public void invoke(OwnerData data, AnalysisContext context) {
        cachedDataList.add(data);
        // 达到BATCH_COUNT了，需要去存储一次数据库，防止数据几万条数据在内存，容易OOM
        if (cachedDataList.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
        }
    }

    /**
     * 所有数据解析完成了 都会来调用
     * @param context 分析上下文
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 这里也要保存数据，确保最后遗留的数据也存储到数据库
        saveData();
//        log.info("所有业主数据解析完成！");
    }

    /**
     * 加上存储数据库
     */
    private void saveData() {
//        log.info("开始存储业主数据，共{}条", cachedDataList.size());
        
        if (cachedDataList.isEmpty()) {
            return;
        }

        // 使用filter过滤有效数据
        List<OwnerData> validDataList = cachedDataList.stream()
                .filter(data -> !StrUtil.isEmpty(data.getName()))
                .filter(data -> !StrUtil.isEmpty(data.getPhone()))
                .filter(data -> !StrUtil.isEmpty(data.getCellName()))
                .filter(data -> !StrUtil.isEmpty(data.getBuildingName()))
                .filter(data -> !StrUtil.isEmpty(data.getUnitName()))
                .filter(data -> !StrUtil.isEmpty(data.getNumber()))
                .filter(data -> isValidEmail(data.getEmail()))
                .toList();

//        log.info("过滤后有效数据{}条", validDataList.size());

        // 转换为Owner实体并保存
        List<Owner> ownerList = validDataList.stream().map(data -> {
            try {

                // 获取小区ID
                Long cellId = cellNameToIdMap.get(data.getCellName());
                if (cellId == null) {
                    throw new BusinessException(ErrorCode.PARAMS_ERROR.getCode(), 
                        String.format("小区名称[%s]不存在，请检查数据", data.getCellName()));
                }

                // 获取房屋ID
                Long houseId = ownerMapper.getHouseIdByBuildingUnitNumber(
                    data.getBuildingName(), data.getUnitName(), data.getNumber(), tenantId);
                if (houseId == null) {
                    throw new BusinessException(ErrorCode.PARAMS_ERROR.getCode(), 
                        String.format("房屋[%s-%s-%s]不存在，请检查数据", 
                            data.getBuildingName(), data.getUnitName(), data.getNumber()));
                }
                SpHouse house = spHouseMapper.selectOneById(houseId);
                if (house.getOwnerId() != null) {
                    throw new BusinessException(ErrorCode.PARAMS_ERROR.getCode(),
                        String.format("房屋[%s-%s-%s]已经被绑定了，请检查数据",
                            data.getBuildingName(), data.getUnitName(), data.getNumber()));
                }

                // 转换性别
                Integer gender = null;
                if (StrUtil.isNotBlank(data.getGender())) {
                    gender = GENDER_MAP.get(data.getGender().trim());
                    if (gender == null) {
                        throw new BusinessException(ErrorCode.PARAMS_ERROR.getCode(), 
                            String.format("性别[%s]格式不正确，请填写：男/女", data.getGender()));
                    }
                }

                // 转换住户身份
                Integer residentType = null;
                if (StrUtil.isNotBlank(data.getResidentType())) {
                    residentType = RESIDENT_TYPE_MAP.get(data.getResidentType().trim());
                    if (residentType == null) {
                        throw new BusinessException(ErrorCode.PARAMS_ERROR.getCode(), 
                            String.format("住户身份[%s]格式不正确，请填写：业主/子女/亲戚/其他", data.getResidentType()));
                    }
                }

                // 构建Owner实体
                Owner owner = new Owner();
                owner.setTenantId(tenantId);
                owner.setCellId(cellId);
                owner.setName(data.getName().trim());
                owner.setPhone(data.getPhone().trim());
                owner.setGender(gender);
                owner.setEmail(StrUtil.isNotBlank(data.getEmail()) ? data.getEmail().trim() : null);
                owner.setIdCard(StrUtil.isNotBlank(data.getIdCard()) ? data.getIdCard().trim() : null);
                owner.setMoveInTime(data.getMoveInTime());
                owner.setResidentType(residentType);
                owner.setRemark(StrUtil.isNotBlank(data.getRemark()) ? data.getRemark().trim() : null);
                owner.setStatus(0); // 待审核状态
                owner.setCreatedTime(new Date());
                owner.setUpdatedTime(new Date());

                return owner;
            } catch (Exception e) {
                throw new BusinessException(ErrorCode.OPERATION_ERROR.getCode(),
                    String.format("业主[%s]数据处理失败：%s，请检查数据格式是否正确",
                        data.getName(), e.getMessage()));
            }
        }).collect(java.util.stream.Collectors.toList());
        
        // 保存到数据库
        try {
            ownerService.saveBatch(ownerList);
            
            // 批量更新房屋的业主ID
            for (int i = 0; i < ownerList.size(); i++) {
                Owner owner = ownerList.get(i);
                OwnerData data = validDataList.get(i);
                
                // 获取房屋ID
                Long houseId = ownerMapper.getHouseIdByBuildingUnitNumber(
                    data.getBuildingName(), data.getUnitName(), data.getNumber(), tenantId);
                
                // 更新房屋的业主ID
                spHouseService.addOwnerIdById(houseId, owner.getId());
            }
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR.getCode(), "批量保存业主数据失败!");
        }

//        log.info("存储业主数据库成功！");
    }
}
